<template>
  <div class="api-test-platform">
    <div class="page-header">
      <h2>API接口测试平台</h2>
      <div class="header-actions">
        <el-button type="primary" icon="Plus" @click="showAddDialog = true">新增接口</el-button>
        <el-button type="success" icon="Collection">测试集合</el-button>
        <el-button icon="Download">导出</el-button>
      </div>
    </div>

    <el-row :gutter="20">
      <!-- 左侧：接口列表 -->
      <el-col :span="8">
        <el-card class="api-list-card">
          <template #header>
            <div class="card-header">
              <span>接口列表</span>
              <el-input
                v-model="searchKeyword"
                placeholder="搜索接口"
                size="small"
                clearable
                prefix-icon="Search"
              />
            </div>
          </template>

          <div class="api-tree">
            <el-tree
              :data="apiTree"
              :props="treeProps"
              node-key="id"
              default-expand-all
              @node-click="handleNodeClick"
            >
              <template #default="{ node, data }">
                <div class="tree-node">
                  <el-icon v-if="data.type === 'folder'"><Folder /></el-icon>
                  <el-tag v-else :type="getMethodType(data.method)" size="small">
                    {{ data.method }}
                  </el-tag>
                  <span class="node-label">{{ node.label }}</span>
                </div>
              </template>
            </el-tree>
          </div>
        </el-card>
      </el-col>

      <!-- 右侧：接口测试 -->
      <el-col :span="16">
        <el-card class="api-test-card">
          <template #header>
            <div class="card-header">
              <span>接口测试</span>
              <el-button type="primary" size="small" @click="sendRequest" :loading="testing">
                <el-icon><Position /></el-icon>
                发送请求
              </el-button>
            </div>
          </template>

          <el-tabs v-model="activeTestTab">
            <!-- 请求配置 -->
            <el-tab-pane label="请求" name="request">
              <el-form :model="requestForm" label-width="100px">
                <el-form-item label="请求方法">
                  <el-select v-model="requestForm.method" style="width: 150px">
                    <el-option label="GET" value="GET" />
                    <el-option label="POST" value="POST" />
                    <el-option label="PUT" value="PUT" />
                    <el-option label="DELETE" value="DELETE" />
                    <el-option label="PATCH" value="PATCH" />
                  </el-select>
                </el-form-item>
                <el-form-item label="请求URL">
                  <el-input v-model="requestForm.url" placeholder="https://api.example.com/v1/..." />
                </el-form-item>

                <!-- Headers -->
                <el-form-item label="Headers">
                  <div class="key-value-editor">
                    <div
                      v-for="(header, index) in requestForm.headers"
                      :key="'header-' + index"
                      class="key-value-row"
                    >
                      <el-input v-model="header.key" placeholder="Key" style="width: 40%" />
                      <el-input v-model="header.value" placeholder="Value" style="width: 40%" />
                      <el-button
                        type="danger"
                        icon="Delete"
                        circle
                        size="small"
                        @click="removeHeader(index)"
                      />
                    </div>
                    <el-button type="primary" size="small" @click="addHeader">
                      <el-icon><Plus /></el-icon>
                      添加Header
                    </el-button>
                  </div>
                </el-form-item>

                <!-- Query Params -->
                <el-form-item label="Query Params">
                  <div class="key-value-editor">
                    <div
                      v-for="(param, index) in requestForm.params"
                      :key="'param-' + index"
                      class="key-value-row"
                    >
                      <el-input v-model="param.key" placeholder="Key" style="width: 40%" />
                      <el-input v-model="param.value" placeholder="Value" style="width: 40%" />
                      <el-button
                        type="danger"
                        icon="Delete"
                        circle
                        size="small"
                        @click="removeParam(index)"
                      />
                    </div>
                    <el-button type="primary" size="small" @click="addParam">
                      <el-icon><Plus /></el-icon>
                      添加参数
                    </el-button>
                  </div>
                </el-form-item>

                <!-- Body -->
                <el-form-item label="Body" v-if="['POST', 'PUT', 'PATCH'].includes(requestForm.method)">
                  <el-radio-group v-model="requestForm.bodyType" style="margin-bottom: 10px">
                    <el-radio-button label="none">None</el-radio-button>
                    <el-radio-button label="json">JSON</el-radio-button>
                    <el-radio-button label="form">Form Data</el-radio-button>
                    <el-radio-button label="raw">Raw</el-radio-button>
                  </el-radio-group>
                  <el-input
                    v-if="requestForm.bodyType !== 'none'"
                    v-model="requestForm.body"
                    type="textarea"
                    :rows="8"
                    placeholder="请输入请求体内容"
                  />
                </el-form-item>
              </el-form>
            </el-tab-pane>

            <!-- 响应结果 -->
            <el-tab-pane label="响应" name="response">
              <div v-if="responseData" class="response-container">
                <div class="response-status">
                  <span class="status-label">状态码：</span>
                  <el-tag :type="getStatusCodeType(responseData.status)">
                    {{ responseData.status }}
                  </el-tag>
                  <span class="time-label">响应时间：</span>
                  <el-tag type="success">{{ responseData.time }}ms</el-tag>
                  <span class="size-label">响应大小：</span>
                  <el-tag type="info">{{ responseData.size }}B</el-tag>
                </div>

                <el-tabs v-model="activeResponseTab" style="margin-top: 15px">
                  <el-tab-pane label="Body" name="body">
                    <div class="json-viewer">
                      <pre>{{ formatJSON(responseData.body) }}</pre>
                    </div>
                  </el-tab-pane>
                  <el-tab-pane label="Headers" name="headers">
                    <el-descriptions :column="1" border>
                      <el-descriptions-item
                        v-for="(value, key) in responseData.headers"
                        :key="key"
                        :label="key"
                      >
                        {{ value }}
                      </el-descriptions-item>
                    </el-descriptions>
                  </el-tab-pane>
                </el-tabs>
              </div>
              <el-empty v-else description="请先发送请求" />
            </el-tab-pane>

            <!-- 测试历史 -->
            <el-tab-pane label="历史" name="history">
              <el-table :data="testHistory" stripe max-height="400">
                <el-table-column prop="timestamp" label="时间" width="180" />
                <el-table-column prop="method" label="方法" width="100">
                  <template #default="{ row }">
                    <el-tag :type="getMethodType(row.method)" size="small">
                      {{ row.method }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="url" label="URL" min-width="200" show-overflow-tooltip />
                <el-table-column prop="status" label="状态码" width="100" align="center">
                  <template #default="{ row }">
                    <el-tag :type="getStatusCodeType(row.status)">
                      {{ row.status }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="time" label="响应时间" width="100" align="right">
                  <template #default="{ row }">
                    {{ row.time }}ms
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="150" fixed="right">
                  <template #default="{ row }">
                    <el-button link type="primary" @click="loadHistory(row)">加载</el-button>
                    <el-button link type="danger" @click="deleteHistory(row)">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </el-tab-pane>

            <!-- 断言 -->
            <el-tab-pane label="断言" name="assertions">
              <el-button type="primary" size="small" @click="addAssertion" style="margin-bottom: 15px">
                <el-icon><Plus /></el-icon>
                添加断言
              </el-button>

              <div class="assertions-list">
                <div
                  v-for="(assertion, index) in requestForm.assertions"
                  :key="'assertion-' + index"
                  class="assertion-row"
                >
                  <el-select v-model="assertion.type" placeholder="断言类型" style="width: 150px">
                    <el-option label="状态码" value="status" />
                    <el-option label="响应时间" value="time" />
                    <el-option label="响应体" value="body" />
                    <el-option label="Header" value="header" />
                  </el-select>
                  <el-select v-model="assertion.operator" placeholder="操作符" style="width: 120px">
                    <el-option label="等于" value="equals" />
                    <el-option label="不等于" value="notEquals" />
                    <el-option label="包含" value="contains" />
                    <el-option label="大于" value="greaterThan" />
                    <el-option label="小于" value="lessThan" />
                  </el-select>
                  <el-input v-model="assertion.expected" placeholder="期望值" style="width: 200px" />
                  <el-button
                    type="danger"
                    icon="Delete"
                    circle
                    size="small"
                    @click="removeAssertion(index)"
                  />
                </div>
              </div>

              <el-divider />

              <div v-if="assertionResults.length > 0" class="assertion-results">
                <h4>断言结果</h4>
                <div
                  v-for="(result, index) in assertionResults"
                  :key="'result-' + index"
                  class="assertion-result"
                  :class="result.passed ? 'passed' : 'failed'"
                >
                  <el-icon v-if="result.passed"><CircleCheck /></el-icon>
                  <el-icon v-else><CircleClose /></el-icon>
                  <span>{{ result.message }}</span>
                </div>
              </div>
            </el-tab-pane>
          </el-tabs>
        </el-card>
      </el-col>
    </el-row>

    <!-- 新增接口对话框 -->
    <el-dialog v-model="showAddDialog" title="新增接口" width="600px">
      <el-form :model="apiForm" label-width="100px">
        <el-form-item label="接口名称">
          <el-input v-model="apiForm.name" placeholder="请输入接口名称" />
        </el-form-item>
        <el-form-item label="接口分组">
          <el-select v-model="apiForm.group" placeholder="请选择分组">
            <el-option label="用户模块" value="user" />
            <el-option label="商品模块" value="product" />
            <el-option label="订单模块" value="order" />
            <el-option label="其他" value="other" />
          </el-select>
        </el-form-item>
        <el-form-item label="请求方法">
          <el-select v-model="apiForm.method">
            <el-option label="GET" value="GET" />
            <el-option label="POST" value="POST" />
            <el-option label="PUT" value="PUT" />
            <el-option label="DELETE" value="DELETE" />
          </el-select>
        </el-form-item>
        <el-form-item label="请求URL">
          <el-input v-model="apiForm.url" placeholder="https://..." />
        </el-form-item>
        <el-form-item label="接口描述">
          <el-input
            v-model="apiForm.description"
            type="textarea"
            :rows="3"
            placeholder="请输入接口描述"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showAddDialog = false">取消</el-button>
        <el-button type="primary" @click="handleApiSubmit">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'

// 搜索关键词
const searchKeyword = ref('')

// 当前标签页
const activeTestTab = ref('request')
const activeResponseTab = ref('body')

// 测试状态
const testing = ref(false)

// 接口树结构
const apiTree = ref([
  {
    id: 1,
    label: '用户模块',
    type: 'folder',
    children: [
      { id: 11, label: '用户登录', type: 'api', method: 'POST', url: '/api/user/login' },
      { id: 12, label: '用户列表', type: 'api', method: 'GET', url: '/api/user/list' },
      { id: 13, label: '创建用户', type: 'api', method: 'POST', url: '/api/user/create' }
    ]
  },
  {
    id: 2,
    label: '商品模块',
    type: 'folder',
    children: [
      { id: 21, label: '商品列表', type: 'api', method: 'GET', url: '/api/product/list' },
      { id: 22, label: '商品详情', type: 'api', method: 'GET', url: '/api/product/detail' },
      { id: 23, label: '创建商品', type: 'api', method: 'POST', url: '/api/product/create' },
      { id: 24, label: '更新商品', type: 'api', method: 'PUT', url: '/api/product/update' },
      { id: 25, label: '删除商品', type: 'api', method: 'DELETE', url: '/api/product/delete' }
    ]
  },
  {
    id: 3,
    label: '订单模块',
    type: 'folder',
    children: [
      { id: 31, label: '订单列表', type: 'api', method: 'GET', url: '/api/order/list' },
      { id: 32, label: '创建订单', type: 'api', method: 'POST', url: '/api/order/create' }
    ]
  }
])

const treeProps = {
  children: 'children',
  label: 'label'
}

// 请求表单
const requestForm = reactive({
  method: 'GET',
  url: '',
  headers: [
    { key: 'Content-Type', value: 'application/json' }
  ],
  params: [],
  bodyType: 'json',
  body: '',
  assertions: []
})

// 响应数据
const responseData = ref(null)

// 断言结果
const assertionResults = ref([])

// 测试历史
const testHistory = ref([
  {
    id: 1,
    timestamp: '2025-01-13 14:30:25',
    method: 'GET',
    url: '/api/user/list',
    status: 200,
    time: 125
  },
  {
    id: 2,
    timestamp: '2025-01-13 14:28:15',
    method: 'POST',
    url: '/api/product/create',
    status: 201,
    time: 256
  }
])

// 对话框
const showAddDialog = ref(false)

// API表单
const apiForm = reactive({
  name: '',
  group: '',
  method: 'GET',
  url: '',
  description: ''
})

// 方法
const getMethodType = (method) => {
  const types = {
    GET: 'success',
    POST: 'primary',
    PUT: 'warning',
    DELETE: 'danger',
    PATCH: 'info'
  }
  return types[method] || 'info'
}

const getStatusCodeType = (status) => {
  if (status >= 200 && status < 300) return 'success'
  if (status >= 300 && status < 400) return 'info'
  if (status >= 400 && status < 500) return 'warning'
  return 'danger'
}

const handleNodeClick = (data) => {
  if (data.type === 'api') {
    requestForm.method = data.method
    requestForm.url = data.url
  }
}

const addHeader = () => {
  requestForm.headers.push({ key: '', value: '' })
}

const removeHeader = (index) => {
  requestForm.headers.splice(index, 1)
}

const addParam = () => {
  requestForm.params.push({ key: '', value: '' })
}

const removeParam = (index) => {
  requestForm.params.splice(index, 1)
}

const addAssertion = () => {
  requestForm.assertions.push({
    type: 'status',
    operator: 'equals',
    expected: '200'
  })
}

const removeAssertion = (index) => {
  requestForm.assertions.splice(index, 1)
}

const formatJSON = (json) => {
  try {
    return JSON.stringify(json, null, 2)
  } catch {
    return json
  }
}

const sendRequest = async () => {
  testing.value = true
  
  // 模拟API请求
  await new Promise(resolve => setTimeout(resolve, 1000))
  
  responseData.value = {
    status: 200,
    time: 125,
    size: 1024,
    body: {
      code: 200,
      message: 'success',
      data: {
        id: 1,
        name: '测试数据',
        value: 'test'
      }
    },
    headers: {
      'Content-Type': 'application/json',
      'X-Request-Id': '123456789'
    }
  }

  // 运行断言
  runAssertions()

  testing.value = false
  activeTestTab.value = 'response'
  ElMessage.success('请求发送成功')

  // 添加到历史
  testHistory.value.unshift({
    id: Date.now(),
    timestamp: new Date().toLocaleString(),
    method: requestForm.method,
    url: requestForm.url,
    status: responseData.value.status,
    time: responseData.value.time
  })
}

const runAssertions = () => {
  assertionResults.value = []
  
  requestForm.assertions.forEach(assertion => {
    let passed = false
    let message = ''

    if (assertion.type === 'status') {
      passed = responseData.value.status == assertion.expected
      message = `状态码 ${responseData.value.status} ${assertion.operator} ${assertion.expected}`
    } else if (assertion.type === 'time') {
      const time = responseData.value.time
      const expected = parseInt(assertion.expected)
      if (assertion.operator === 'lessThan') {
        passed = time < expected
      }
      message = `响应时间 ${time}ms ${assertion.operator} ${expected}ms`
    }

    assertionResults.value.push({ passed, message })
  })
}

const loadHistory = (row) => {
  requestForm.method = row.method
  requestForm.url = row.url
  activeTestTab.value = 'request'
  ElMessage.success('历史记录已加载')
}

const deleteHistory = (row) => {
  const index = testHistory.value.findIndex(item => item.id === row.id)
  if (index > -1) {
    testHistory.value.splice(index, 1)
    ElMessage.success('删除成功')
  }
}

const handleApiSubmit = () => {
  console.log('添加接口', apiForm)
  ElMessage.success('接口添加成功')
  showAddDialog.value = false
}
</script>

<style scoped lang="scss">
.api-test-platform {
  padding: 20px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;

  h2 {
    margin: 0;
    font-size: 24px;
    color: #303133;
  }
}

.api-list-card {
  height: calc(100vh - 200px);

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .api-tree {
    max-height: calc(100vh - 320px);
    overflow-y: auto;

    .tree-node {
      display: flex;
      align-items: center;
      gap: 8px;
      flex: 1;

      .node-label {
        flex: 1;
      }
    }
  }
}

.api-test-card {
  height: calc(100vh - 200px);
  overflow-y: auto;
}

.key-value-editor {
  .key-value-row {
    display: flex;
    gap: 10px;
    margin-bottom: 10px;
    align-items: center;
  }
}

.response-container {
  .response-status {
    padding: 15px;
    background: #f5f7fa;
    border-radius: 4px;
    display: flex;
    align-items: center;
    gap: 15px;

    .status-label,
    .time-label,
    .size-label {
      color: #606266;
      font-weight: 500;
    }
  }

  .json-viewer {
    background: #f5f7fa;
    padding: 15px;
    border-radius: 4px;
    max-height: 400px;
    overflow: auto;

    pre {
      margin: 0;
      font-family: 'Courier New', monospace;
      font-size: 13px;
      color: #303133;
    }
  }
}

.assertions-list {
  .assertion-row {
    display: flex;
    gap: 10px;
    margin-bottom: 15px;
    align-items: center;
  }
}

.assertion-results {
  h4 {
    margin: 0 0 15px 0;
    color: #303133;
  }

  .assertion-result {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border-radius: 4px;
    margin-bottom: 10px;

    &.passed {
      background: #f0f9ff;
      color: #67c23a;
    }

    &.failed {
      background: #fef0f0;
      color: #f56c6c;
    }
  }
}
</style>

